/*
 * 程序清单：这是一个 CAN2 设备使用例程
 * 例程导出了 can2_tx 命令到控制终端
 * 程序功能：通过 CAN2 设备发送一帧，并创建一个线程接收数据然后打印输出。
*/

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#define CAN2_DEV_NAME       "fdcan2"

static rt_device_t can2_dev;
static struct rt_semaphore can2_rx_sem;
static struct rt_mutex can2_print_lock;

static rt_err_t can2_rx_call(rt_device_t dev, rt_size_t size)
{
    rt_sem_release(&can2_rx_sem);
    return RT_EOK;
}

static void can2_rx_thread(void *parameter)
{
    rt_err_t res;
    struct rt_can_msg rxmsg = {0};

    can2_dev = rt_device_find(CAN2_DEV_NAME);
    if (!can2_dev)
    {
        rt_kprintf("find %s failed!\n", CAN2_DEV_NAME);
        return;
    }

    rt_sem_init(&can2_rx_sem, "can2_rx", 0, RT_IPC_FLAG_FIFO);
    rt_mutex_init(&can2_print_lock, "can2_prt", RT_IPC_FLAG_PRIO);

    res = rt_device_open(can2_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
    RT_ASSERT(res == RT_EOK);

    res = rt_device_control(can2_dev, RT_CAN_CMD_SET_BAUD, (void *)CAN125kBaud);
    RT_ASSERT(res == RT_EOK);

    res = rt_device_set_rx_indicate(can2_dev, can2_rx_call);
    RT_ASSERT(res == RT_EOK);

    rt_kprintf("CAN2 initialized successfully\n");

    while (1)
    {
        rxmsg.hdr = -1;
        rt_sem_take(&can2_rx_sem, RT_WAITING_FOREVER);
        rt_device_read(can2_dev, 0, &rxmsg, sizeof(rxmsg));
        
        rt_mutex_take(&can2_print_lock, RT_WAITING_FOREVER);
        rt_kprintf("[CAN2 RX] ID:%08X  DATA:", rxmsg.id);
        for (uint8_t i = 0; i < rxmsg.len; i++)
        {
            rt_kprintf("%02X ", rxmsg.data[i]);
        }
        rt_kprintf("\n");
        rt_mutex_release(&can2_print_lock);
    }
}

int app_can2_init(void)
{
    rt_thread_t thread;

    thread = rt_thread_create("can2_rx", can2_rx_thread, RT_NULL, 1024, 12, 10);
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        rt_kprintf("create can2_rx thread failed!\n");
        return -RT_ERROR;
    }

    return RT_EOK;
}

static int can2_tx(int argc, char **argv)
{
    struct rt_can_msg msg = {0};
    rt_size_t size = 0;

    if (can2_dev == RT_NULL)
    {
        rt_kprintf("CAN2 device not initialized!\n");
        return -RT_ERROR;
    }

    msg.id = 0x200;
    msg.ide = RT_CAN_STDID;
    msg.rtr = RT_CAN_DTR;
    msg.len = 8;
    
    msg.data[0] = 0xAA;
    msg.data[1] = 0xBB;
    msg.data[2] = 0xCC;
    msg.data[3] = 0xDD;
    msg.data[4] = 0xEE;
    msg.data[5] = 0xFF;
    msg.data[6] = 0x00;
    msg.data[7] = 0x11;

    size = rt_device_write(can2_dev, 0, &msg, sizeof(msg));
    
    rt_mutex_take(&can2_print_lock, RT_WAITING_FOREVER);
    if (size == 0)
    {
        rt_kprintf("CAN2 send data failed!\n");
    }
    else
    {
        rt_kprintf("[CAN2 TX] ID:%08X sent successfully\n", msg.id);
    }
    rt_mutex_release(&can2_print_lock);
    
    return RT_EOK;
}

MSH_CMD_EXPORT(can2_tx, CAN2 send test data);

